/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.classcode.enhance.bytebuddy.classgen;

import com.hyts.classcode.enhance.bytebuddy.interceptor.GlobalInterceptor;
import com.hyts.scanner.utility.StringUtils;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.NamingStrategy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.time.Clock;
import java.time.ZoneId;

/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.classcode.enhance.bytebuddy.classgen
 * @author:LiBo/Alex
 * @create-date:2020-04-23 16:17
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description:
 *
 *    首先NamingStrategy是对生成的类的一个命名策略，其中SuffixingRandom是在父类的基础上，在类名前加一个指定的前缀后面再加一个随机数。
 *    调用subclass指定继承的父类，返回的是一个DynamicType.Builder，所以这里用的是一个Builder模式，具体可以做那些事情可以在Builder里面查看。
 *    Method是对类里面的方法做处理，传入的参数是ElementMatchers的匹配器，这个匹配器可以对各种情况进行过滤，比如函数的返回值，参数，名字，annotation，
 *    那个类定义的等等情况。
 *    Intercept是拦截器，对匹配到的对象做对应的操作，在这里我用到了两种情况，一种是对函数的返回值类型进行匹配，然后然后用FixedValue返回固定的值；
 *    另外一种就是通过对annotation进行匹配，然后重新指定一个拦截器类，转到拦截器类的实现。
 */
public class AnnotationClassGenerator implements ClassGenerator<Class>{

    /**
     * 前置随机字符串
     */
    private String prefixName;

    /**
     * 后置随机字符串
     */
    private String suffixName;

    /**
     * annotationClass 注解类
     */
    private Class annoationClass;

    /**
     * 默认构造器
     */
    public AnnotationClassGenerator(Class annoationClass) {
        // 默认前置不进行随机处理
        this.prefixName = "";
        // 生成当前的毫秒数据值
        this.suffixName = String.valueOf(Clock.system(ZoneId.systemDefault()).instant());
        // 注释类
        this.annoationClass = annoationClass;
    }

    /**
     * 子类构造器
     * @param suffixName 后置名称
     */
    public AnnotationClassGenerator(String suffixName,Class annoationClass) {
        // 默认前置不进行随机处理
        this.prefixName = "";
        // 生成当前的毫秒数据值
        this.suffixName = StringUtils.isBlank(suffixName)?suffixName:String.valueOf(Clock.system(ZoneId.systemDefault()).instant());
        // 注释类
        this.annoationClass = annoationClass;
    }

    /**
     * 子类构造器
     * @param prefixName
     * @param suffixName
     */
    public AnnotationClassGenerator(String prefixName, String suffixName,Class annoationClass) {
        // 默认前置不进行随机处理
        this.prefixName = prefixName;
        // 生成当前的毫秒数据值
        this.suffixName = StringUtils.isBlank(suffixName)?suffixName:String.valueOf(Clock.system(ZoneId.systemDefault()).instant());
        // 注释类
        this.annoationClass = annoationClass;
    }

    /**
     * 创建生成代码子类实现
     * @param clazz
     * @return
     */
    @Override
    public Class generate(Class clazz) {
        NamingStrategy namingStrategy = new NamingStrategy.SuffixingRandom(this.suffixName);
        // subClass生成配置服务集合
        Class<?> subClass = new ByteBuddy().
                with(namingStrategy).
                subclass(clazz).
                method(ElementMatchers.isAnnotatedWith(this.annoationClass)).
                intercept(MethodDelegation.to(GlobalInterceptor.class)).
                make().load(getClass().getClassLoader()).getLoaded();
        return subClass;
    }

    /**
     * 注释类拦截器操作服务
     */
    static class AnnotationClassInterceptor{


    }

}
